#include <interface\winElmt.h>
#include <interface\window.h>
#include <interface\gl.h>

#include <interface\frame.h>

#include <cstdio>

winElmt::winElmt(): parentWin( NULL ),
                    parentSet( NULL ),
                    ELname( "<NONE>" ),
                    mouseOver( false ),
                    active( false ),
                    dragging( false ),
                    inActivable( false ),
                    useLayout( true ),
                    left_pressed( false ),
                    left_released( true ),
                    styleS( NULL ),
                    nextFocus( NULL ){
        enc.left = 0;
        enc.right = 0;
        enc.top = 0;
        enc.bottom = 0;
}

winElmt::winElmt(window* wd):   parentWin( wd ),
                                parentSet( NULL ),
                                ELname( "<NONE>" ),
                                mouseOver( false ),
                                active( false ),
                                dragging( false ),
                                inActivable( false ),
                                useLayout( true ),
                                left_pressed( false ),
                                left_released( true ),
                                styleS( NULL ),
                                nextFocus( NULL ){
        enc.left = 0;
        enc.right = 0;
        enc.top = 0;
        enc.bottom = 0;
}
winElmt::~winElmt(){
    printf("Element removed: %s\n",ELname.c_str());
}

void winElmt::setStyle(styleSheet* ss){
    styleS = ss;
}

void winElmt::setInactivable(bool val){
    inActivable = val;
}
bool winElmt::getInactivable(){
    return inActivable;
}

void winElmt::move(int xoff,int yoff){
    enc.bottom += yoff;
    enc.top += yoff;
    enc.left += xoff;
    enc.right += xoff;
}

void winElmt::setNextFocus(winElmt* nxt){
    nextFocus = nxt;
}

void winElmt::setParentWin(window* wd){
    parentWin = wd;
}

void winElmt::setParentSet(fieldSet* fr){
    parentSet = fr;
    fr->addToElmts(this);
}
fieldSet* winElmt::getParentSet(){
    return parentSet;
}

color* winElmt::bkgColFromSS(elTy type){
    if( !styleS ) return NULL;
    color* out;
    if( active && (out = styleS->getColor(ELTY(type,bkg_st_active))) ) return out;
    if( mouseOver && (out = styleS->getColor(ELTY(type,bkg_st_hover))) ) return out;
    if( (out = styleS->getColor(ELTY(type,bkg_st_normal))) ) return out;
    return styleS->getColor(STATUS(bkg_st_normal));
}
color* winElmt::txtColFromSS(elTy type){
    if( !styleS ) return NULL;
    color* out;
    if( active && (out = styleS->getColor(ELTY(type,txt_st_active))) ) return out;
    if( mouseOver && (out = styleS->getColor(ELTY(type,txt_st_hover))) ) return out;
    if( (out = styleS->getColor(ELTY(type,txt_st_normal))) ) return out;
    return styleS->getColor(STATUS(txt_st_normal));
}

bool winElmt::isMouseOver(){
    return mouseOver;
}
bool winElmt::isActive(){
    return active;
}

int winElmt::getWidth(){
    return enc.right - enc.left;
}
int winElmt::getHeight(){
    return enc.top - enc.bottom;
}
void winElmt::setWidth(int wid){
    enc.right = enc.left + wid;
}
void winElmt::setHeight(int hei){
    enc.top = enc.bottom + hei;
}
void winElmt::setPos(int xpos,int ypos){
    move( xpos - enc.left, ypos - enc.bottom );
}
void winElmt::getPos(int* xpos,int* ypos){
    *xpos = enc.left;
    *ypos = enc.bottom;
}

void winElmt::setRect(RECT rec){
    enc = rec;
}
RECT winElmt::getRect(){
    return enc;
}
string winElmt::getELname(){
    return ELname;
}
void winElmt::setRect(int x,int y,int wid,int hei){
    enc.left = x;
    enc.right = x+wid;
    enc.top = y+hei;
    enc.bottom = y;
}

void winElmt::display(){
    if( !parentWin ) return;
    glEnable(GL_SCISSOR_TEST);
}
void winElmt::display_end(){
    glDisable(GL_SCISSOR_TEST);
}

void winElmt::getOffset(int* xoff,int* yoff){
    int PX = 0;
    int PY = 0;
    if( parentSet ){
        parentSet->getPos(&PX, &PY );
        parentSet->getOffset( &PX, &PY);
    }
    *xoff += PX;
    *yoff += PY;
}

unsigned char winElmt::eventExec(unsigned char in){
    if( !parentWin ) return in;
    int pOffX = 0;
    int pOffY = 0;
    getOffset(&pOffX,&pOffY);
    if( in & ACTIVE_TAKEN ){
        parentWin->getInput()->setKey(VK_TAB,0);
        if( active )activeLoseEvent();
    }
    else if( active ){
        if( nextFocus && parentWin->getInput()->bindKey(VK_TAB) ){
            activeLoseEvent();
            nextFocus->activeGetEvent();
        }
    }
    if( !(in & OVER_TAKEN ) ){
        int MX = parentWin->getInput()->getMouseX();
        int MY = parentWin->getInput()->getMouseY();
        if( MX >= enc.left+pOffX && MX < enc.right+pOffX && MY >= enc.bottom+pOffY && MY < enc.top+pOffY ){
            if( !mouseOver ) mouseGetOverEvent();
            in |= OVER_TAKEN;
            if( parentWin->getInput()->getClk(LEFT_CLICK) ){
                if( !left_pressed && left_released ){
                    mousePushEvent(0);
                    if( !active && !inActivable ) activeGetEvent();
                    in |= ACTIVE_TAKEN;
                    if( inActivable ) in |= NOT_ACTIVABLE;
                }
                left_released = false;
            }
            else{
                if( left_pressed ){
                    mouseReleaseEvent(0);
                    mouseClickEvent(0);
                }
                if( !parentWin->getInput()->getClk(LEFT_CLICK) && !left_released ){
                    left_released = true;
                }
            }
        }else if( mouseOver ) mouseQuitOverEvent();
    }else if( mouseOver ) mouseQuitOverEvent();

    if( !parentWin->getInput()->getClk(LEFT_CLICK) && !left_released ){
        left_released = true;
        left_pressed = false;
    }

    if( left_pressed && !dragging){
        oldX = dragBX = parentWin->getInput()->getMouseX();
        oldY = dragBY = parentWin->getInput()->getMouseY();
        dragging = true;
    }else if( left_pressed && dragging ){
        int dispX = parentWin->getInput()->getMouseX() - oldX;
        int dispY = parentWin->getInput()->getMouseY() - oldY;
        if( dispX != 0 || dispY != 0 ){
            draggingEvent( dispX, dispY);
            oldX += dispX;
            oldY += dispY;
        }
    }else if( left_released && dragging ){
        draggingEvent( parentWin->getInput()->getMouseX() - oldX, parentWin->getInput()->getMouseY() - oldY );
        dragEvent(dragBX,dragBY,parentWin->getInput()->getMouseX(),parentWin->getInput()->getMouseY());
        dragging = false;
    }

    return in;
}

void winElmt::activeGetEvent(){
        active = true;
}
void winElmt::activeLoseEvent(){
        active = false;
}

void winElmt::mouseGetOverEvent(){
        mouseOver = true;
        left_released = false;
}
void winElmt::mouseQuitOverEvent(){
        mouseOver = false;
}

void winElmt::dragEvent(int,int,int,int){}
void winElmt::draggingEvent(int,int){}

void winElmt::mousePushEvent(int){
        left_pressed = true;
}
void winElmt::mouseReleaseEvent(int){
        left_pressed = false;
}
void winElmt::mouseClickEvent(int){}
